package com.leyou.order.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.auth.pojo.UserHolder;
import com.leyou.common.constants.LyConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.client.ItemClient;
import com.leyou.item.entity.Sku;
import com.leyou.order.dto.CartDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.dto.OrderStatusEnum;
import com.leyou.order.dto.OrderVO;
import com.leyou.order.entity.Order;
import com.leyou.order.entity.OrderDetail;
import com.leyou.order.entity.OrderLogistics;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Connection对象  执行crud  控制事务  默认自动提交 autoCommit=true
 */
@Slf4j
@Service
@Transactional
public class OrderService extends ServiceImpl<OrderDetailMapper, OrderDetail> {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private OrderLogisticsMapper orderLogisticsMapper;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private PayHelper payHelper;

    public Long createOrder(OrderDTO orderDTO) {
        try {
            //保存订单
            //创建订单对象
            Order order = new Order();
            order.setStatus(OrderStatusEnum.INIT.value());
            order.setSourceType(2);
            order.setInvoiceType(0);
            order.setPaymentType(orderDTO.getPaymentType());
            order.setUserId(UserHolder.getUserId());
            order.setPostFee(0L);
            //获取到购买的购物车集合
            List<CartDTO> carts = orderDTO.getCarts();
            //将列表集合的购物袋对象转成map集合
            Map<Long, Integer> cartMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
            //获取购买的skuid的集合
            List<Long> skuIds = carts.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
            //根据skuId集合查询sku对象集合
            List<Sku> skus = itemClient.findSkusByIds(skuIds);
            //计算总金额
            long totalFee = skus.stream().mapToLong(sku -> sku.getPrice() * cartMap.get(sku.getId())).sum();
            order.setTotalFee(totalFee);
            order.setActualFee(1L);
            //保存订单
            orderMapper.insert(order);

            //获取订单号
            Long orderId = order.getOrderId();

            //保存订单详情
            //提供一个订单详情集合
            List<OrderDetail> detailList = new ArrayList<>();
            skus.forEach(sku -> {
                //创建一个OrderDetail对象
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setSkuId(sku.getId());
                orderDetail.setOrderId(orderId);
                orderDetail.setImage(StringUtils.substringBefore(sku.getImages(), ","));
                orderDetail.setOwnSpec(sku.getOwnSpec());
                orderDetail.setPrice(sku.getPrice());
                orderDetail.setTitle(sku.getTitle());
                orderDetail.setNum(cartMap.get(sku.getId()));
                detailList.add(orderDetail);
            });
            //保存订单详情
            saveBatch(detailList);

            //保存订单物流
            //获取物流的dto对象
            AddressDTO addressDTO = userClient.queryAddressById(UserHolder.getUserId(), orderDTO.getAddressId());
            //把物流dto对象转成entity对象
            OrderLogistics orderLogistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
            //把订单号赋值给物流对象
            orderLogistics.setOrderId(orderId);
            //保存物流信息
            orderLogisticsMapper.insert(orderLogistics);

            //减库存
            itemClient.minusStock(cartMap);
            return orderId;
        }catch (Exception e){
            e.printStackTrace();
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    public OrderVO findOrderById(Long id) {
        //根据id查询订单
        Order order = orderMapper.selectById(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //将order对象转成OrderVo对象
        OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);

        OrderDetail entity = new OrderDetail();
        entity.setOrderId(id);
        QueryWrapper<OrderDetail> wrapper = Wrappers.query(entity);
        //根据订单号查询订单详情
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(wrapper);
        if(CollectionUtils.isEmpty(orderDetails)){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        orderVO.setDetailList(orderDetails);

        OrderLogistics orderLogistics = orderLogisticsMapper.selectById(id);
        if(orderLogistics==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        orderVO.setLogistics(orderLogistics);
        return orderVO;
    }

    public String getPayUrl(Long id) {
        //获取当前订单支付链接在redis中的key值
        String key = LyConstants.PAY_URL_PRE+id;
        //从redis中获取支付链接
        String payUrl = redisTemplate.opsForValue().get(key);
        //判空
        if(StringUtils.isNotEmpty(payUrl)){
            return payUrl;
        }
        //根据id查询订单
        Order order = orderMapper.selectById(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //判断订单状态
        if(!order.getStatus().equals(OrderStatusEnum.INIT.value())){
            throw new LyException(501, "不要重复支付！");
        }
        //调用微信统一下单接口
        payUrl = payHelper.getPayUrl(id, order.getActualFee());
        //把支付链接放入redis中
        redisTemplate.opsForValue().set(key, payUrl, 2, TimeUnit.HOURS);
        return payUrl;
    }

    public Integer findStatus(Long id) {
        //根据id查询订单
        Order order = orderMapper.selectById(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }

    public Map<String, String> wxNotify(Map<String, String> wxParams) {
        //校验数据
        payHelper.checkResp(wxParams);
        //获取微信通知的订单号
        String outTradeNo = wxParams.get("out_trade_no");
        //获取用户支付金额
        String totalFee = wxParams.get("total_fee");
        //根据订单号查询订单
        Order order = orderMapper.selectById(Long.valueOf(outTradeNo));
        if(order==null){
            log.error("【微信回调通知】失败，订单不存在！");
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //校验金额是否一致
        if(!Long.valueOf(totalFee).equals(order.getActualFee())){
            log.error("【微信回调通知】失败，支付金额不一致！");
            throw new LyException(501, "支付金额不一致!");
        }
        //修改订单状态
        Order entity = new Order();
        entity.setOrderId(Long.valueOf(outTradeNo));
        entity.setStatus(OrderStatusEnum.PAY_UP.value());
        int count = orderMapper.updateById(entity);
        if(count==0){
            log.error("【微信回调通知】失败，数据库订单状态更新失败！");
        }
        Map<String, String> result = new HashMap<>();
        result.put("return_code", "SUCCESS");
        result.put("return_msg", "OK");
        return result;
    }

}